package com.piece.core.web.exception;

import com.piece.core.framework.constant.ExceptionConstants;
import com.piece.core.framework.support.convert.Convert;
import com.piece.core.framework.support.response.AjaxResponse;
import com.piece.core.framework.util.basic.I18nUtil;
import com.piece.core.framework.util.collection.MapUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.ErrorProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Controller
@ConditionalOnMissingBean(HandlerExceptionResolver.class)
public class DefaultErrorController extends BasicErrorController {

    public DefaultErrorController() {
        super(new DefaultErrorAttributes(), initProperties());
    }

    public static ErrorProperties initProperties() {
        ErrorProperties properties = new ErrorProperties();
        properties.setIncludeMessage(ErrorProperties.IncludeAttribute.ALWAYS);
        return properties;
    }

    @Override
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.getErrorAttributeOptions(request, MediaType.ALL)));
        AjaxResponse response = AjaxResponse.error(convertErrorInfo(model.get("message")));
        Map<String, Object> responseEntity = MapUtil.builder(new HashMap<String, Object>()).put("code", response.getCode())
                .put("msg", response.getMsg())
                .put("param", response.getParam())
                .put("headers", response.getHeaders())
                .build();
        return new ResponseEntity<>(responseEntity, HttpStatus.OK);
    }

    @Override
    public ModelAndView errorHtml(HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> model = Collections.unmodifiableMap(this.getErrorAttributes(request, this.getErrorAttributeOptions(request, MediaType.ALL)));
        response.setStatus(HttpStatus.OK.value());
        request.setAttribute("errInfo", convertErrorInfo(model.get("message")));
        return new ModelAndView("/error/500");
    }

    private String convertErrorInfo(Object message) {
        if ("No message available".equals(message.toString())) {
            message = null;
        }

        return Convert.toStr(message, I18nUtil.message(ExceptionConstants.SERVER));
    }
}
